package com.machine.bootstatemachine.service.ordermachine;

import com.alibaba.fastjson.JSON;
import com.machine.bootstatemachine.domain.Order;
import com.machine.bootstatemachine.enums.OrderEventEnum;
import com.machine.bootstatemachine.enums.OrderStatueEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.statemachine.StateMachine;
import org.springframework.statemachine.config.StateMachineFactory;
import org.springframework.statemachine.persist.StateMachinePersister;
import org.springframework.stereotype.Component;

import java.util.Map;

/**
 * @Author daijinwu01
 * @Date 2021/12/27
 */
@Slf4j
@Component
public class OrderMachineHandler {

    @Autowired
    private StateMachineFactory<OrderStatueEnum, OrderEventEnum> stateMachineFactory;

    @Autowired
    private StateMachinePersister<OrderStatueEnum, OrderEventEnum, Order> stateMachinePersist;

    public boolean execute(OrderEventEnum event, Order order, Map<String, Object> map) {
        StateMachine<OrderStatueEnum, OrderEventEnum> stateMachine =
                stateMachineFactory.getStateMachine(order.getOrderId().toString());

        stateMachine.start();
        try {
            stateMachinePersist.restore(stateMachine, order);
            // 消息构建
            MessageBuilder<OrderEventEnum> messageBuilder = MessageBuilder
                    .withPayload(event)
                    .setHeader("order", order);

            // 填充扩展字段
            if (map != null) {
                map.forEach((key, value) -> messageBuilder.setHeader(key, value));
            }
            Message<OrderEventEnum> message = messageBuilder.build();

            boolean success = stateMachine.sendEvent(message);
            log.info("OrderStatus orderId:{},event:{} ", order.getOrderId(), event);
            if (success) {
                stateMachinePersist.persist(stateMachine, order);
                return true;
            } else {
                String s = String.format("(%s)操作失败,请核对竞拍单状态或刷新后继续操作。", JSON.toJSONString(order));
                throw new RuntimeException(s);
            }
        } catch (Exception e) {
            log.error("状态机初始化异常：" + JSON.toJSONString(order), e);
            throw new RuntimeException("初始化状态失败");
        } finally {
            stateMachine.stop();
        }

    }

}
